
import abc

"""
{
  "type": "ACCEPT",
  "framework_id": {
    "value": "12220-3440-12532-2345"
  },
  "accept": {
    "offer_ids": [
      {
        "value": "12220-3440-12532-O12"
      }
    ],
    "operations": [
      {
        "type": "LAUNCH",
        "launch": {
          "task_infos": [
            {
              "name": "My Task",
              "task_id": {
                "value": "12220-3440-12532-my-task"
              },
              "agent_id": {
                "value": "12220-3440-12532-S1233"
              },
              "executor": {
                "command": {
                  "shell": true,
                  "value": "sleep 1000"
                },
                "executor_id": {
                  "value": "12214-23523-my-executor"
                }
              },
              "resources": [
                {
                  "allocation_info": {
                    "role": "*"
                  },
                  "name": "cpus",
                  "role": "*",
                  "type": "SCALAR",
                  "scalar": {
                    "value": 1.0
                  }
                },
                {
                  "allocation_info": {
                    "role": "*"
                  },
                  "name": "mem",
                  "role": "*",
                  "type": "SCALAR",
                  "scalar": {
                    "value": 128.0
                  }
                }
              ]
            }
          ]
        }
      }
    ],
    "filters": {
      "refuse_seconds": 5.0
    }
  }
}
"""

class JsonType(object):
    __metaclass__ = abc.ABCMeta

    @abc.abstractmethod
    def json_serial(self):
        return None


class ValueType(JsonType):
    """
    {"value": "12220-3440-12532-S1233"}
    Extends:
            JsonType
    """

    def __init__(self, value):
        super(ValueType, self).__init__()
        self.value = value

    def json_serial(self):
        return {"value": self.value}


class Executor(JsonType):
    """docstring for Executor"""

    def __init__(self):
        super(Executor, self).__init__()
        self.executor_id = None

class SpecialCommandExecutor(Executor):
    """[summary]

    "executor": {
            "command": {
              "shell": true,
              "value": "sleep 1000"
            },
            "executor_id": {
              "value": "12214-23523-my-executor"
            }
          }
    [description]

    Extends:
            Executor
    """

    def __init__(self):
        super(SpecialCommandExecutor, self).__init__()
        self.type = "executor"
        self.shell = True
        self.value = "sleep 1000"

    def json_serial(self):
        r = {}
        r["command"] = {"shell": self.shell, "value": self.value}
        r["executor_id"] = self.executor_id.json_serial()
        return r

class CommandExecutor(Executor):
    """
        "command": {
          "shell": true,
          "value": "sleep 1000"
        }
    Extends:
            Executor
    """

    def __init__(self, command, shell=True):
        super(CommandExecutor, self).__init__()
        self.type = "command"
        self.shell = shell
        self.value = command

    def json_serial(self):
        r = {"shell": self.shell, "value": self.value}
        return r

class Resource(JsonType):
    """
    {
      "allocation_info": {
        "role": "*"
      },
      "name": "cpus",
      "role": "*",
      "type": "SCALAR",
      "scalar": {
        "value": 1.0
      }
    }
    Extends:
            JsonType
    """

    def __init__(self):
        super(Resource, self).__init__()
        self.role = "*"
        self.name = None
        self.allocation_info = None
        self.type = None
        self.type_value = None

    def json_serial(self):
        r = {}
        r["allocation_info"] = {"role": self.allocation_info}
        r["name"] = self.name
        r["role"] = self.role
        r["type"] = self.type.upper()
        r[self.type.lower()] = self.type_value.json_serial()
        return r


class TaskInfo(JsonType):
    """
    {
      "name": "My Task",
      "task_id": {
        "value": "12220-3440-12532-my-task"
      },
      "agent_id": {
        "value": "12220-3440-12532-S1233"
      },
      ["executor": {...}|"command": {...}],
      "resources": [...]
    }
    Extends:
            JsonType
    """

    def __init__(self, name, task_id):
        super(TaskInfo, self).__init__()
        self.name = name
        self.task_id = ValueType(task_id)
        self.agent_id = None
        self.executor = None
        self.resources = []

    def json_serial(self):
        r = {}
        r["name"] = self.name
        r["task_id"] = self.task_id.json_serial()
        r["agent_id"] = self.agent_id.json_serial()
        r[self.executor.type] = self.executor.json_serial()
        r["resources"] = []
        for resource in self.resources:
            r["resources"].append(resource.json_serial())
        return r


class Operation(JsonType):
    """docstring for Operation"""

    def __init__(self):
        super(Operation, self).__init__()
        self.type = None
        self.type_value = None


class LanuchOperation(Operation):
    """
    {
      "type": "LAUNCH",
      "launch": {
        "task_infos": [...]
      }
    }

    Extends:
            Operation
    """

    def __init__(self):
        super(LanuchOperation, self).__init__()
        self.type = "LAUNCH"
        self.task_infos = []

    def json_serial(self):
        tasks = []
        r = {"type": self.type, "launch": {"task_infos": tasks}}
        for task in self.task_infos:
            tasks.append(task.json_serial())
        return r


class AcceptType(JsonType):
    """
    {
        "offer_ids": [
          {
            "value": "12220-3440-12532-O12"
          }
        ],
        "operations": [...],
        "filters": {
          "refuse_seconds": 5.0
        }
    }
    Extends:
            JsonType
    """

    def __init__(self):
        super(AcceptType, self).__init__()
        self.offer_ids = []
        self.operations = []
        self.filters = 5.0

    def json_serial(self):
        r = {"offer_ids": [], "operations": []}
        for offer_id in self.offer_ids:
            r["offer_ids"].append(offer_id.json_serial())
        for operation in self.operations:
            r["operations"].append(operation.json_serial())
        r["filters"] = {"refuse_seconds": 5.0}
        return r


class SchedulerType(JsonType):
    """
    {
      "type": "ACCEPT",
      "framework_id": {
        "value": "12220-3440-12532-2345"
      },
      "accept": {}
    }
    Extends:
            JsonType
    """

    def __init__(self, type_name, framework_id):
        super(SchedulerType, self).__init__()
        self.type = type_name
        self.type_value = None
        self.framework_id = None
        if framework_id != None:
            self.framework_id = ValueType(framework_id)

    def json_serial(self):
        r = {}
        r["type"] = self.type.upper()
        if self.framework_id != None:
            r["framework_id"] = self.framework_id.json_serial()
        r[self.type.lower()] = self.type_value.json_serial()
        return r

class FramworkInfoType(JsonType):
    """docstring for FramworkInfoType"""
    def __init__(self):
        super(FramworkInfoType, self).__init__()
        self.id = None
        self.name = None
        self.user = None
        self.roles = []
        self.capabilities = []

    def json_serial(self):
        r = {}
        if self.id != None:
            r["id"] = self.id.json_serial()
        r["name"] = self.name
        r["user"] = self.user
        if len(self.roles) > 0:
            r["roles"] = []
            for role in self.roles:
                r["roles"].append(role)
        if len(self.capabilities) > 0:
            r["capabilities"] = []
            for cap in self.capabilities:
                r["capabilities"].append({"type": cap})
        return r

class SubscribeType(JsonType):
    """
    {
       "type"       : "SUBSCRIBE",
       "subscribe"  : {
          "framework_info"  : {
            "user" :  "foo",
            "name" :  "Example HTTP Framework",
            "roles": ["test"],
            "capabilities" : [{"type": "MULTI_ROLE"}]
          }
      }
    }
    Extends:
        JsonType
    """
    def __init__(self):
        super(SubscribeType, self).__init__()
        self.type = "SUBSCRIBE"
        self.framework_info = None

    def json_serial(self):
        r = {}
        r["framework_info"] = self.framework_info.json_serial()
        rr = {}
        rr["type"] = self.type.upper()
        rr[self.type.lower()] = r
        return rr

class ReSubcribeType(JsonType):
    """
    {
     "type"       : "SUBSCRIBE",
     "subscribe"  : {
        "framework_info"  : {
          "id"   : {"value": "xxx-framework_id-xxx"},
          "user" :  "foo",
          "name" :  "Example HTTP Framework",
          "roles": ["test"],
          "capabilities" : [{"type": "MULTI_ROLE"}]
        }
      },
      "framework_id": {"value": "xxx-framework_id-xxx"}
    }
    Extends:
      JsonType
    """

    def __init__(self, framework_id):
        super(ReSubcribeType, self).__init__()
        self.framework_id = framework_id
        self.type = "SUBSCRIBE"
        self.framework_info = framework_info
        self.framework_id = ValueType(framework_id)

    def json_serial(self):
        r = {}
        r["framework_info"] = self.framework_info.json_serial()
        rr = {}
        rr["type"] = self.type.upper()
        rr[self.type.lower()] = r
        rr["framework_id"] = self.framework_id.json_serial()
        return rr

class DeclineType(JsonType):
    """docstring for DeclineType"""
    def __init__(self, framework_id):
        super(DeclineType, self).__init__()
        self.framework_id = ValueType(framework_id)
        self.offer_ids = []
    def add_offer_id(self, id):
        self.offer_ids.append(ValueType(id))

    def json_serial(self):
        r = {}
        r["framework_id"] = self.framework_id.json_serial()
        r["type"] = "DECLINE"
        r["decline"] = {}
        r["decline"]["filters"] = {"refuse_seconds" : 5.0}
        r["decline"]["offer_ids"] = []
        for offer_id in self.offer_ids:
            r["decline"]["offer_ids"].append(offer_id.json_serial())
        return r
        
class AcknowledgeType(JsonType):
    """docstring for AcknowledgeType"""
    def __init__(self, framework_id, agent_id, task_id, uuid):
        super(AcknowledgeType, self).__init__()
        self.framework_id = ValueType(framework_id)
        self.agent_id = ValueType(agent_id)
        self.task_id = ValueType(task_id)
        self.uuid = uuid

    def json_serial(self):
        r = {}
        r["type"] = "ACKNOWLEDGE"
        r["acknowledge"] = {
        "agent_id": self.agent_id.json_serial(),
        "task_id": self.task_id.json_serial(),
        "uuid": self.uuid
        }
        r["framework_id"] = self.framework_id.json_serial()
        return r

        